package common.utils;

import java.math.BigDecimal;
import java.text.DecimalFormat;

/**
 * 数学计算
 * 修改入参double转换为BigDecimal为：double-->String-->BigDecimal
 * 原因：double d1 = 0.06 -->BigDecimal b_d1 = 0.059999999999999997779553950749686919152736663818359375
 * 如果去尾保留两位小数，则和输入的原值有较大出入。
 * 统一修改为先转换为String在转换为BigDecimal进行计算
 * 
 * @author fudl
 * 
 */
public abstract class MathCalcUtil {
	/**
	 * bigDecimal也会将大数输出为科学计算法格式。所以添加格式化字段
	 * 默认保留5位有效小数
	 */
	private static DecimalFormat df = new DecimalFormat("#0.00000");

	/**
	 * 加法
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static double add(double d1, double d2) {
		// 进行加法运算
		BigDecimal b1 = new BigDecimal(df.format(d1));
		BigDecimal b2 = new BigDecimal(df.format(d2));
		return b1.add(b2).doubleValue();
	}

	/**
	 * 进行减法运算
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static double sub(double d1, double d2) { 
		BigDecimal b1 = new BigDecimal(df.format(d1));
		BigDecimal b2 = new BigDecimal(df.format(d2));
		return b1.subtract(b2).doubleValue();
	}

	/**
	 * 进行乘法运算
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static double multiply(double d1, double d2) {
		BigDecimal b1 = new BigDecimal(df.format(d1));
		BigDecimal b2 = new BigDecimal(df.format(d2));
		return b1.multiply(b2).doubleValue();
	}

	/**
	 * 进行除法运算
	 * @param d1
	 * @param d2
	 * @param len 保留小数点位数,四舍五入
	 * @return
	 */
	public static double div(double d1, double d2, int len) {
		return divByRound(d1,d2,len,BigDecimal.ROUND_HALF_UP);
	}
	/**
	 * 进行除法运算（截取有效小数点）
	 * @param d1
	 * @param d2
	 * @param len 保留小数点位数,直接截取
	 * @return
	 */
	public static double divByRoundDown(double d1, double d2, int len) {
		return divByRound(d1,d2,len,BigDecimal.ROUND_DOWN);
	}
	/**
	 * 定义除法和截取类型
	 * @param d1
	 * @param d2
	 * @param len
	 * @param round
	 * @return
	 */
	public static double divByRound(double d1, double d2, int len,int round) {
		BigDecimal b1 = new BigDecimal(df.format(d1));
		BigDecimal b2 = new BigDecimal(df.format(d2));
		return b1.divide(b2, len, round).doubleValue();
	}
	/**
	 * 保留小数点位数，四舍五入 BigDecimal.ROUND_HALF_UP
	 * @param d
	 * @param len
	 * @return
	 */
	public static double round(double d,int len) {     
		BigDecimal b1 = new BigDecimal(df.format(d));
		BigDecimal b2 = new BigDecimal("1");
		// 任何一个数字除以1都是原数字
		// ROUND_HALF_UP是BigDecimal的一个常量，表示进行四舍五入的操作
		return b1.divide(b2, len,BigDecimal.ROUND_HALF_UP).doubleValue();
	}
	
	/**
	 * 保留小数点位数，后面直接截取
	 * @param d
	 * @param len
	 * @return
	 */
	public static double roundDown(double d,int len) {     
		BigDecimal b1 = new BigDecimal(df.format(d));
		BigDecimal b2 = new BigDecimal("1");
		// 任何一个数字除以1都是原数字
		// ROUND_HALF_UP是BigDecimal的一个常量，表示进行四舍五入的操作
		return b1.divide(b2,len,BigDecimal.ROUND_DOWN).doubleValue();
	}
	
	/**
	 * 在一定的精度内，比较两个double数大小
	 * >0 表示 d1>d2;
	 * ==0 表示 d1=d2;
	 * <0 表示 d1<d2;
	 * @param d1
	 * @param d2
	 * @return
	 * @throws Exception 
	 */
	public static int compareValue (double d1,double d2,int len) {
		d1 = MathCalcUtil.round(d1,len);
		d2 = MathCalcUtil.round(d2,len);
		double result =  MathCalcUtil.sub(d1, d2);
		result = MathCalcUtil.round(result,len);
		if(result > 0){
			return 1;
		}else if(result == 0){
			return 0;
		}else{
			return -1;
		}
	}
	
	/**
	 * 将double转化为字符串
	 * double可以为科学记数法
	 * @param d
	 * @param len
	 * @return
	 */
	public static String double2String(double d,int len){
		BigDecimal b1 = new BigDecimal(df.format(d));
		BigDecimal b2 = new BigDecimal("1");
		// 任何一个数字除以1都是原数字
		return b1.divide(b2,len,BigDecimal.ROUND_DOWN).toString();
	}
	/**
	 * 在一定的精度内，比较两个double数大小
	 * >0 表示 d1>d2
	 * ==0 表示 d1=d2
	 * <0 表示 d1<d2
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static int compareValue4Square (double d1,double d2,int len){
		d1 = MathCalcUtil.roundDown(d1,len);
		d2 = MathCalcUtil.roundDown(d2,len);
		double result =  MathCalcUtil.sub(d1, d2);
		result = MathCalcUtil.roundDown(result,len);
		if(result > 0){
			return 1;
		}else if(result == 0){
			return 0;
		}else{
			return -1;
		}
	}

}
